﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Bluefly;
using System.ComponentModel;


namespace BlueFlyPhone.Model
{


    public class VarioModel : BaseViewModel, IVarioView 
    {

        #region Private fields
        
        IVarioService _varioService;

        PositionService positionService;

        Position _position; 
        double _pressure;
        double _altitude;
        double _climbrate;

        #endregion

        #region Constructor

        public VarioModel(IVarioService service )
        {
            ConnectionState = Bluefly.ConnectionState.STATE_NONE;
            this._varioService = service;
           
            BatteryDisplayUnit = "% Charge";
   
            _varioService.BatteryVoltageUpdated += _service_BatteryVoltageChanged;
            _varioService.PressureUpdated += _service_PressureUpdated;
            _varioService.TemperatureUpdated += _service_TemperatureUpdated;
            _varioService.ConnectionStateUpdated += _service_ConnectionStateUpdated;

            _position = new Bluefly.Position() { Source = Bluefly.PositionSource.Unknown };
            positionService = new PositionService();
            positionService.PositionUpdated += positionService_PositionUpdated;


        }

        void positionService_PositionUpdated(object sender, PositionEventArgs e)
        {
            _position = e.Position;
            RaisePropertyChangedOnUIThread("Latitude", "Longitude", "GPSAltitude", "Velocity", "Heading", "PositionSource", "GPSAltitudeAccuracy");
        }




        #endregion

        #region Public Properties

        public double Temperature
        {
            get;
            private set;
        }

        public string Pressure
        {
            get { return UnitConverterService.PressureConverter.ConvertToDisplayUnits(_pressure, 1); }
        }

        public string Altitude
        {
            get { return  UnitConverterService.AltitudeConverter.ConvertToDisplayUnits(_altitude, 0);  }
        }


        public string Latitude
        {
            get { return _position.Latitude.ToString(); }
        }


        public string Longitude
        {
            get { return _position.Longitude.ToString(); }
        }

        public string GPSAltitude
        {
            get { return _position.Altitude.ToString(); }
        }

        public string GPSAltitudeAccuracy
        {
            get { return _position.AltitudeAccuracy.HasValue ? _position.AltitudeAccuracy.Value.ToString() : "na"; }
        }

        public string Velocity
        {
            get { return !_position.Velocity.HasValue || double.IsNaN(_position.Velocity.Value) ? "-" : _position.Velocity.Value.ToString(); }
        }
        
        public string Heading
        {
            get { return !_position.Heading.HasValue || double.IsNaN(_position.Heading.Value) ? "-" : _position.Heading.Value.ToString(); }
        }


        public PositionSource PositionSource
        {
            get { return _position.Source; }

        }
       
        public string Climbrate
        {
            get { return UnitConverterService.VarioConverter.ConvertToDisplayUnits(_climbrate, 1); }
            
        }

        public double BatteryCharge
        {
            get;
            private set;
        }


        public Position Position
        {
            get { return _position; }
        }


        public ConnectionState ConnectionState
        {
            get;
            private set;
        }


        public string AltitudeDisplayUnit
        {
            get { return UnitConverterService.AltitudeConverter.DisplayUnit; }
        }

        public string PressureDisplayUnit
        {
            get { return UnitConverterService.PressureConverter.DisplayUnit; }
        }

        public string VarioDisplayUnit
        {
            get { return UnitConverterService.VarioConverter.DisplayUnit; }
        }

        public string BatteryDisplayUnit
        {
            get;
            private set;
        }

        public override IEnumerable<string> Errors
        {
            get { return _varioService.Errors; }
        }


        #endregion

        #region Private methods


        void _service_TemperatureUpdated(object sender, TemperatureEventArgs e)
        {
            if (e.Temperature != Temperature)
            {
                Temperature = e.Temperature;
                RaisePropertyChangedOnUIThread("Temperature");
            }
        }


        void _service_ConnectionStateUpdated(object sender, ConnectionStateEventArgs e)
        {

                ConnectionState = e.NewState;
                
                RaisePropertyChangedOnUIThread("ConnectionState");
                
                if (e.NewState == Bluefly.ConnectionState.STATE_ERROR)
                    RaisePropertyChangedOnUIThread("Errors");
            

        }


        void _service_BatteryVoltageChanged(object sender, BatteryEventArgs e)
        {
            if (e.Charge != this.BatteryCharge)
            {
                BatteryCharge = Math.Round(e.Charge * 100,0);
                RaisePropertyChangedOnUIThread("BatteryCharge");
            }
        }


        bool havePressure = false;




        void _service_PressureUpdated(object sender, PressureEventArgs e)
        {

            havePressure = true;
            var  pressure =  Math.Round((double)e.Pressure,1);  //kpa
            
            
            if (_pressure != pressure)
            {
                _pressure = pressure;
                RaisePropertyChangedOnUIThread("Pressure");
            }

            var alt = Math.Round(e.DampedAltitude, 0);
            if (_altitude != alt)
            {
                _altitude = alt;
                RaisePropertyChangedOnUIThread("Altitude");
            }

            var climb = Math.Round(e.KalmanClimbrate, 1);
            if(climb != _climbrate)
            {
                _climbrate = climb;
                RaisePropertyChangedOnUIThread("Climbrate");
            }

            _position = positionService.Position;
            RaisePropertyChangedOnUIThread("Position");

        }

        #endregion



    }
}
